#include "KmyTrans.h"
#include "../KmyRandom.h"

#include <cstring>

KmyTrans::KmyTrans(int screen_w, int screen_h)
{
    data16 = new u16[64*64];
//    memset(data16, 0, 256*64*2);
    tex = new KmyITexture(KmyITexture::TEXTURE_MODE_ARGB4,
                          (const u8*)data16, 64, 64, true);
    setColor(0xffff);
    this->width = screen_w;
    this->height = screen_h;
    step = 0;
    rects = NULL;
    rect_num = 0;
}

void KmyTrans::finalize(){
    delete[] data16;
    data16 = NULL;
    delete tex;
}

int KmyTrans::getNodeType(){
    return KmyNode::NODE_TYPE_TEXTLAYER;
}

void KmyTrans::setColor(u16 rgba){
    int* p = (int*)data16;
    int c = (rgba<<16)|rgba;
    for (int i=0; i<tex->width*tex->height/2; i++){
        *p++ = c;
    };
    tex->is_changed = true;
}

void KmyTrans::startRandomTrans(int time){
    KmyRandom *random = KmyRandom::getInstance();
    int t = random->getRandom(7);
    int f = random->getRandom(4);
    startTrans(t, f, time);
}

void KmyTrans::startTrans(int type, int from, int time){
    this->time = time*60/1000;
    this->from = from;
    this->trans_type = type;
    if (rect_num!=0){
        delete[] rects;
    }
    switch (type){
    case TRANS_TYPE_NONE:
    {
        rect_num = 1;
        rects = new St_Rect[rect_num];
        rects[0].x = 0;
        rects[0].y = 0;
        rects[0].w = width;
        rects[0].h = height;
    }break;
    case TRANS_TYPE_1: //大块平移
    {
        rect_num = 1;
        rects = new St_Rect[rect_num];
        rects[0].w = width;
        rects[0].h = height;
        switch (this->from){
        case 0:
            rects[0].x = -width;
            rects[0].y = 0;
            break;
        case 1:
            rects[0].x = width;
            rects[0].y = 0;
            break;
        case 2:
            rects[0].x = 0;
            rects[0].y = -height;
            break;
        case 3:
            rects[0].x = 0;
            rects[0].y = height;
            break;
        }
    }break;
    case TRANS_TYPE_2: //卷帘
    {

        switch (this->from){
        case 0:
            rect_num = 8;
            rects = new St_Rect[rect_num];
            for (int i=0; i<rect_num; i++){
                rects[i].w = 0;
                rects[i].h = height;
                rects[i].x = i*width/rect_num;
                rects[i].y = 0;
            }
            break;
        case 1:
            rect_num = 8;
            rects = new St_Rect[rect_num];
            for (int i=0; i<rect_num; i++){
                rects[i].w = 0;
                rects[i].h = height;
                rects[i].x = i*width/rect_num;
                rects[i].y = 0;
            }
            break;
        case 2:
            rect_num = 6;
            rects = new St_Rect[rect_num];
            for (int i=0; i<rect_num; i++){
                rects[i].w = width;
                rects[i].h = 0;
                rects[i].x = 0;
                rects[i].y = i*height/rect_num;
            }
            break;
        case 3:
            rect_num = 6;
            rects = new St_Rect[rect_num];
            for (int i=0; i<rect_num; i++){
                rects[i].w = width;
                rects[i].h = 0;
                rects[i].x = 0;
                rects[i].y = i*height/rect_num;
            }
            break;
        }
    }break;
    case TRANS_TYPE_3:  //方块
    {
        rect_num = 10*6;
        rects = new St_Rect[rect_num];
        for (int i=0; i<6; i++){
            for (int j=0; j<10; j++){
                rects[i*10+j].w = 0;
                rects[i*10+j].h = 0;
                rects[i*10+j].x = j*width/10;
                rects[i*10+j].y = i*height/6;
            }
        }
    }break;
    }
    step = 1;
    delay = this->time;
}

void KmyTrans::logic(){
    if (step == 1){ // trans in
        delay--;
        switch(trans_type){
        case TRANS_TYPE_1:
            switch (this->from){
            case 0:
                rects[0].x = -width*delay/time;
                break;
            case 1:
                rects[0].x = width*delay/time;
                break;
            case 2:
                rects[0].y = -height*delay/time;
                break;
            case 3:
                rects[0].y = height*delay/time;
                break;
            }
            break;
        case TRANS_TYPE_2:
            switch (this->from){
            case 0:
                for (int i=0; i<rect_num; i++){
                    rects[i].w = (time-delay)*width/(time*rect_num);
                }
                break;
            case 1:
                for (int i=0; i<rect_num; i++){
                    rects[i].w = (time-delay)*width/(time*rect_num);
                    rects[i].x = (i+1)*width/rect_num-rects[i].w;
                }
                break;
            case 2:
                for (int i=0; i<rect_num; i++){
                    rects[i].h = (time-delay)*height/(time*rect_num);
                }
                break;
            case 3:
                for (int i=0; i<rect_num; i++){
                    rects[i].h = (time-delay)*height/(time*rect_num);
                    rects[i].y = (i+1)*height/rect_num-rects[i].h;
                }
                break;
            }

            break;
        case TRANS_TYPE_3:
//            switch (this->from){
//            case 0:
//                break;
//            case 1:
//                break;
//            case 2:
//                break;
//            case 3:
//                break;
//            }
            for (int i=0; i<rect_num; i++){
                rects[i].w = (time-delay)*width/(time*10);
                rects[i].h = (time-delay)*height/(time*6);
            }
            break;
        }
        if (delay<=0){
            step = 2;
            delay = 10;
        }
        is_updated = true;
    }else if (step == 2){ // full
        delay--;
        if (delay<=0){
            delay = time;
            step = 3;
        }
    }else if (step == 3){ // trans out
        delay--;
        switch(trans_type){
        case TRANS_TYPE_1:
            switch (this->from){
            case 0:
                rects[0].x = width*(time-delay)/time;
                break;
            case 1:
                rects[0].x = -width*(time-delay)/time;
                break;
            case 2:
                rects[0].y = height*(time-delay)/time;
                break;
            case 3:
                rects[0].y = height*(time-delay)/time;
                break;
            }
            break;
        case TRANS_TYPE_2:
            switch (this->from){
            case 0:
                for (int i=0; i<rect_num; i++){
                    rects[i].w = delay*width/(time*rect_num);
                    rects[i].x = (i+1)*width/rect_num-rects[i].w;
                }
                break;
            case 1:
                for (int i=0; i<rect_num; i++){
                    rects[i].w = delay*width/(time*rect_num);
                }
                break;
            case 2:
                for (int i=0; i<rect_num; i++){
                    rects[i].h = delay*height/(time*rect_num);
                    rects[i].y = (i+1)*height/rect_num-rects[i].h;
                }
                break;
            case 3:
                for (int i=0; i<rect_num; i++){
                    rects[i].h = delay*height/(time*rect_num);
                }
                break;
            }

            break;
        case TRANS_TYPE_3:
//            switch (this->from){
//            case 0:
//                break;
//            case 1:
//                break;
//            case 2:
//                break;
//            case 3:
//                break;
//            }
            for (int i=0; i<rect_num; i++){
                rects[i].w = delay*width/(time*10);
                rects[i].h = delay*height/(time*6);
                rects[i].x = (i%10+1)*width/10-rects[i].w;
                rects[i].y = (i/10+1)*height/6-rects[i].h;
            }
            break;
        }
        is_updated = true;
        if (delay<=0){
            step = 0;
            if (rect_num>0){
                delete[] rects;
                rects = NULL;
                rect_num = 0;
            }
        }
    }
}

void KmyTrans::render(KmyICanvas *screen){
    if (rect_num==0){
        return;
    }
    if (step == 1){ // trans in
//        switch (trans_type){
//        case TRANS_TYPE_1:
//        {

//        }break;
//        case TRANS_TYPE_2:
//        {

//        }break;
//        case TRANS_TYPE_3:
//        {

//        }break;
//        }
        St_Rect srect;
        srect.x = 0;
        srect.y = 0;
        srect.w = tex->width;
        srect.h = tex->height;
        St_Rect2 *drects = new St_Rect2[rect_num];
        for (int i=0; i<rect_num; i++){
            if (rects[i].w*rects[i].h>0){
//                screen->addDrawTaskImageF2(tex, 0, 0, tex->width, tex->height,
//                rects[i].x, rects[i].y, rects[i].w, rects[i].h, getGlobalZ()
//                );
                drects[i].x = rects[i].x;
                drects[i].y = rects[i].y;
                drects[i].w = rects[i].w;
                drects[i].h = rects[i].h;
                drects[i].flip = 0;
            }
        }
        if (rects[0].w*rects[0].h>0){
            if (drawtask==NULL){
                drawtask = screen->addDrawTaskDupliImage(tex,
                                          &srect, rect_num, drects,
                                          getGlobalZ());
            }else{
                // update drawtask
                if (is_updated){
                    drawtask->updatePlural(&srect, rect_num, drects,
                                           getGlobalZ(), 1.0, 0);
                    is_updated = false;
                }
                screen->addDrawTask(drawtask);
            }
        }
        if (rect_num>0){
            delete[] drects;
        }
    }else if (step == 2){// full
        if (drawtask==NULL){
            drawtask = screen->addDrawTaskImageF2(tex,
                                   0, 0, tex->width, tex->height,
                                   0, 0, screen->WIDTH, screen->HEIGHT, getGlobalZ());
        }else{
            // update drawtask
            if (is_updated){
                drawtask->updateRegion(0, 0, tex->width, tex->height,
                                       0, 0, screen->WIDTH, screen->HEIGHT,
                                       getGlobalZ(), 1.0, 0);
                is_updated = false;
            }
            screen->addDrawTask(drawtask);
        }
    }else if (step == 3){// trans out
        St_Rect srect;
        srect.x = 0;
        srect.y = 0;
        srect.w = tex->width;
        srect.h = tex->height;
        St_Rect2 *drects = new St_Rect2[rect_num];
        for (int i=0; i<rect_num; i++){
            if (rects[i].w*rects[i].h>0){
//                screen->addDrawTaskImageF2(tex,
//                                           0, 0, tex->width, tex->height,
//                rects[i].x, rects[i].y, rects[i].w, rects[i].h, getGlobalZ()
//                );
                drects[i].x = rects[i].x;
                drects[i].y = rects[i].y;
                drects[i].w = rects[i].w;
                drects[i].h = rects[i].h;
                drects[i].flip = 0;
            }
        }
        if (rects[0].w*rects[0].h>0){
            if (drawtask==NULL){
                drawtask = screen->addDrawTaskDupliImage(tex,
                                          &srect, rect_num, drects,
                                          getGlobalZ());
            }else{
                //// update drawtask
                if (is_updated){
                    drawtask->updatePlural(&srect, rect_num, drects,
                                           getGlobalZ(), 1.0, 0);
                    is_updated = false;
                }
                screen->addDrawTask(drawtask);
            }
        }
        if (rect_num>0){
            delete[] drects;
        }
    }
}
